"""
全局错误处理中间件
统一处理所有异常，返回规范的错误响应
"""
import logging
import traceback
from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import JSONResponse
from sqlalchemy.exc import SQLAlchemyError, IntegrityError
from pydantic import ValidationError

logger = logging.getLogger(__name__)


def setup_error_handlers(app: FastAPI):
    """
    配置全局错误处理器
    
    Args:
        app: FastAPI 应用实例
    """
    
    @app.exception_handler(HTTPException)
    async def http_exception_handler(request: Request, exc: HTTPException):
        """处理 HTTP 异常"""
        logger.warning(
            f"HTTP {exc.status_code}: {exc.detail} | "
            f"Path: {request.url.path} | "
            f"Method: {request.method}"
        )
        
        return JSONResponse(
            status_code=exc.status_code,
            content={
                "success": False,
                "error": {
                    "code": exc.status_code,
                    "message": exc.detail,
                    "type": "http_error"
                }
            }
        )
    
    @app.exception_handler(ValidationError)
    async def validation_exception_handler(request: Request, exc: ValidationError):
        """处理 Pydantic 验证错误"""
        errors = []
        for error in exc.errors():
            field = " -> ".join(str(loc) for loc in error['loc'])
            errors.append({
                "field": field,
                "message": error['msg'],
                "type": error['type']
            })
        
        logger.warning(f"验证错误: {errors} | Path: {request.url.path}")
        
        return JSONResponse(
            status_code=422,
            content={
                "success": False,
                "error": {
                    "code": 422,
                    "message": "请求参数验证失败",
                    "type": "validation_error",
                    "details": errors
                }
            }
        )
    
    @app.exception_handler(ValueError)
    async def value_error_handler(request: Request, exc: ValueError):
        """处理值错误"""
        logger.error(
            f"ValueError: {str(exc)} | "
            f"Path: {request.url.path} | "
            f"Method: {request.method}"
        )
        
        return JSONResponse(
            status_code=400,
            content={
                "success": False,
                "error": {
                    "code": 400,
                    "message": str(exc) or "请求参数错误",
                    "type": "value_error"
                }
            }
        )
    
    @app.exception_handler(IntegrityError)
    async def integrity_error_handler(request: Request, exc: IntegrityError):
        """处理数据库完整性错误（如唯一约束冲突）"""
        error_msg = str(exc.orig) if hasattr(exc, 'orig') else str(exc)
        
        # 提取用户友好的错误信息
        if 'unique constraint' in error_msg.lower() or 'duplicate' in error_msg.lower():
            message = "该数据已存在，请勿重复添加"
        elif 'foreign key' in error_msg.lower():
            message = "关联的数据不存在或已被删除"
        else:
            message = "数据操作失败，请检查输入"
        
        logger.error(
            f"IntegrityError: {error_msg} | "
            f"Path: {request.url.path} | "
            f"Method: {request.method}"
        )
        
        return JSONResponse(
            status_code=409,
            content={
                "success": False,
                "error": {
                    "code": 409,
                    "message": message,
                    "type": "integrity_error"
                }
            }
        )
    
    @app.exception_handler(SQLAlchemyError)
    async def sqlalchemy_error_handler(request: Request, exc: SQLAlchemyError):
        """处理数据库错误"""
        logger.error(
            f"SQLAlchemyError: {str(exc)} | "
            f"Path: {request.url.path} | "
            f"Method: {request.method}",
            exc_info=True
        )
        
        return JSONResponse(
            status_code=500,
            content={
                "success": False,
                "error": {
                    "code": 500,
                    "message": "数据库操作失败，请稍后重试",
                    "type": "database_error"
                }
            }
        )
    
    @app.exception_handler(PermissionError)
    async def permission_error_handler(request: Request, exc: PermissionError):
        """处理权限错误"""
        logger.warning(
            f"PermissionError: {str(exc)} | "
            f"Path: {request.url.path} | "
            f"Method: {request.method}"
        )
        
        return JSONResponse(
            status_code=403,
            content={
                "success": False,
                "error": {
                    "code": 403,
                    "message": str(exc) or "无权限执行此操作",
                    "type": "permission_error"
                }
            }
        )
    
    @app.exception_handler(FileNotFoundError)
    async def file_not_found_handler(request: Request, exc: FileNotFoundError):
        """处理文件未找到错误"""
        logger.error(
            f"FileNotFoundError: {str(exc)} | "
            f"Path: {request.url.path}"
        )
        
        return JSONResponse(
            status_code=404,
            content={
                "success": False,
                "error": {
                    "code": 404,
                    "message": "文件不存在或已被删除",
                    "type": "file_not_found"
                }
            }
        )
    
    @app.exception_handler(Exception)
    async def general_exception_handler(request: Request, exc: Exception):
        """处理所有未捕获的异常"""
        # 记录完整的堆栈跟踪
        logger.error(
            f"Unhandled exception: {type(exc).__name__}: {str(exc)} | "
            f"Path: {request.url.path} | "
            f"Method: {request.method} | "
            f"Traceback: {traceback.format_exc()}"
        )
        
        # 生产环境不暴露详细错误信息
        return JSONResponse(
            status_code=500,
            content={
                "success": False,
                "error": {
                    "code": 500,
                    "message": "服务器内部错误，请联系管理员",
                    "type": "internal_error"
                }
            }
        )

